package com.p2p.front.facade.impl;

import java.util.Date;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.Transactional;

import com.p2p.base.exception.BizException;
import com.p2p.base.model.Money;
import com.p2p.front.async.AsyncBiz;
import com.p2p.front.component.TenderPointSetting;
import com.p2p.front.dal.model.LoanInfo;
import com.p2p.front.dal.model.LoanVariation;
import com.p2p.front.dal.model.MemberPointLog;
import com.p2p.front.dal.model.Tender;
import com.p2p.front.enums.TenderStatus;
import com.p2p.front.enums.UserCreditsType;
import com.p2p.front.facade.UserTenderFacade;
import com.p2p.front.result.UserTenderResult;
import com.p2p.front.service.LoanInfoService;
import com.p2p.front.service.LoanVariationService;
import com.p2p.front.service.MemberPointService;
import com.p2p.front.service.TenderAmountSumService;
import com.p2p.front.service.TenderService;
import com.p2p.front.service.UserCreditsService;
import com.p2p.front.task.LoanTimeOpenTask;
import com.p2p.front.tender.AbstractTenderBiz;
import com.p2p.front.tender.FlowLoanTender;
import com.p2p.front.tender.NormalLoanTender;
import com.p2p.trans.client.enums.FreezeBalanceTypeEnum;
import com.p2p.trans.client.facade.AccountQueryFacade;
import com.p2p.trans.client.facade.AccountTransFacade;
import com.p2p.trans.client.model.AccountVO;
import com.p2p.trans.client.model.TransInfo;
import com.p2p.trans.client.result.AccountQueryResult;
import com.p2p.trans.client.result.AccountTransResult;
import com.p2p.user.facade.UserQueryFacade;
import com.p2p.user.result.UserQueryResult;
import com.p2p.user.vo.UserInfoFullVO;

/**
 * @author ruiqi
 *
 */
@Service("userTenderFacade")
public class UserTenderFacadeImpl implements UserTenderFacade {

	private final Logger logger = LoggerFactory
			.getLogger(UserTenderFacadeImpl.class);
	
	@Resource
	private PlatformTransactionManager transactionManager;

	private double tenderPointProduce= 1d;

	@Resource
	private LoanVariationService loanVariationService;

	@Resource
	private LoanInfoService loanInfoService;

	@Resource
	private AccountTransFacade remoteAccountTransFacade;

	@Resource
	private AccountQueryFacade remoteAccountQueryFacade;

	@Resource
	private UserQueryFacade userQueryFacade;

	@Resource
	private TenderService tenderService;

	@Resource
	private AsyncBiz asyncBiz;

	@Resource
	private FlowLoanTender flowLoanTender;

	@Resource
	private NormalLoanTender normalLoanTender;
	
	@Resource
	private MemberPointService memberPointService;
	
	@Resource
	private LoanTimeOpenTask loanTimeOpenTask;
	
	@Resource
	private TenderPointSetting tenderPointSetting;

	@Resource
	private UserCreditsService userCreditsService;
	
	@Resource
	private TenderAmountSumService tenderAmountSumService;
	
	public void init(){
		
	}
	public void initTenderPointProduce(){
		
	}
	public UserTenderResult doTenderBiz(String uid, Long lid, Money amount,int auto,Integer autoRank) {
		UserTenderResult result = new UserTenderResult();

		LoanInfo loanInfo = loanVariationService.getLoanInfoFromCache(lid);
		if (loanInfo == null) {
			result.setResultCode(UserTenderResult.ResultCodeEnum.tender_common_error
					.name());
			return result;
		}
		if(amount.getCent()<10000L){
			result.setResultCode(UserTenderResult.ResultCodeEnum.tender_amount_error
					.name());
			return result;
		}
		if (loanInfo.getStatus() != 21) {
			
			boolean bool = false;
			if(loanInfo.getStatus() == 12){
				Date tenderBegin= loanInfo.getTenderBegin();
				if(tenderBegin.getTime()<System.currentTimeMillis()){
					bool = true;
				}
			}
			
			if(!bool){
				result.setResultCode(UserTenderResult.ResultCodeEnum.tender_status_error
						.name());
				return result;
			}
			
		}
		
		if(auto==0){
			if(loanInfo.getAuto()!=2){
				result.setResultCode(UserTenderResult.ResultCodeEnum.tender_auto_run
						.name());
				asyncBiz.asyncStartAutoTendeScan(loanTimeOpenTask);
				return result;
			}
			
		}else if(auto==1){
			if(loanInfo.getAuto()!=1){
				result.setResultCode(UserTenderResult.ResultCodeEnum.tender_status_error
						.name());
				return result;
			}
		}
		UserQueryResult userQueryResult = userQueryFacade.getUserInfoById(uid);
		if (!userQueryResult.isSuccess()) {
			result.setResultCode(userQueryResult.getResultCode());
			return result;
		}
		UserInfoFullVO userInfoFullVO = userQueryResult.getUserInfoFullVO();

		try {
			this.checkTenderPrepare(userInfoFullVO, lid, amount);

			Tender newTender = tenderService.createTender(loanInfo,
					Long.valueOf(uid), userInfoFullVO.getAccountNo(),userInfoFullVO.getUname(), amount,auto,autoRank);
			AbstractTenderBiz tenderBizModule = getTenderModule(loanInfo);
			result = tenderBizModule.doBizTransaction(newTender);
			if (result.isSuccess()) {
				memberPointService.cumulative(String.valueOf(newTender.getUid()), tenderPointSetting.calcuTenderPoint(newTender.getAmount(),loanInfo.getDeadline()), MemberPointLog.TypeEnum.TENDER_SUCCESE);
				userCreditsService.subValue(uid, UserCreditsType.UserCreditsNeedCharge, result.getTenderAmount().getCent());
				tenderAmountSumService.sumAmountForTotal(newTender);
				if (result.isTenderFull()) {
					tenderBizModule.doTenderFullBiz(loanInfo.getLid());
				}
			}
		} catch (BizException e) {
			logger.error("tender exception", e);
			result.setResultCode(e.getCode());
			return result;
		} catch (Exception e) {
			logger.error("tender exception", e);
			result.setResultCode(e.getMessage());
			return result;
		}
		return result;
	}
	
	@Transactional
	@Override
	public UserTenderResult doTenderCancelBiz(Long tid,Long uid, Long lid){
		UserTenderResult result = new UserTenderResult();
		Tender tender = tenderService.getByTidAndUid(tid, uid);
		LoanVariation  loanVariation = loanVariationService.selectByIdForUpdate(lid);
		Money subMoney = loanVariation.subTenderAmount(tender.getAmount());
		if(subMoney.getCent()>0){
			tenderService.updateTenderStatus(tid, TenderStatus.INVALID.getCode());
			loanVariationService.update(loanVariation);
			TransInfo transInfo = new TransInfo();
			transInfo.setTransAccountOut(tender.getUserAccount());
			transInfo.setTransAmount(tender.getAmount());
			transInfo.setFreezeType(FreezeBalanceTypeEnum.FREEZE_FOR_TENDER);
			transInfo.setTransMemo("流标解冻");
			AccountTransResult transResult = this.remoteAccountTransFacade.doUnFreeze(transInfo);
			if(transResult.isSuccess()==false){
				logger.error("fall unfreeze code="+transResult.getResultCode());
				throw new BizException(transResult.getResultCode());
			}else{
				result.setSuccess(true);
			}
			
		}
		
		return result;
		
	}
	
	private boolean checkAutoRun(LoanInfo loanInfo){
		if(loanInfo.getAuto()==2){
			return true;
		}else{
			if(loanInfo.getAuto()==0){
				
			}
			return false;
		}
	}
	private AbstractTenderBiz getTenderModule(LoanInfo loanInfo) {
		if (loanInfo.getIsFlow() == 1) {
			
			return flowLoanTender;
			
		} else {
			
			return normalLoanTender;
		}
	}

	public void checkTenderPrepare(UserInfoFullVO userInfoFullVO, Long lid,
			Money amount) throws BizException {
		String accountNo = userInfoFullVO.getAccountNo();
		AccountVO accountVO = getAccountVO(accountNo);
		if (accountVO == null) {
			throw new BizException(
					UserTenderResult.ResultCodeEnum.tender_account_exist.name());
		}
		Money canUserBalance = accountVO.getCanUserBalance();
		if (canUserBalance.getCent() < amount.getCent()) {
			throw new BizException(
					UserTenderResult.ResultCodeEnum.tender_balance_enough
							.name());
		}

	}

	private AccountVO getAccountVO(String accountNo) {
		AccountQueryResult queryResult = remoteAccountQueryFacade
				.getAccountInfo(accountNo);
		if (queryResult.isSuccess()) {
			AccountVO accountVO = queryResult.getAccountVO();
			return accountVO;
		}
		return null;
	}

}
